package net.logax.games.chase;

import javax.microedition.khronos.opengles.GL10;

import net.logax.games.chase.map.fragment.MapCorridor;
import net.logax.games.chase.map.fragment.MapCurve;
import net.logax.games.chase.map.fragment.MapStairs;
import net.logax.games.chase.map.fragment.MapStart;
import net.logax.games.chase.map.fragment.MapTCrossing;
import net.logax.games.chase.map.fragment.MapYCrossing;
import net.logax.games.framework.Game;
import net.logax.games.framework.Screen;
import net.logax.games.framework.gl.Camera2D;
import net.logax.games.framework.gl.EulerCamera;
import net.logax.games.framework.gl.ObjSerLoader;
import net.logax.games.framework.gl.PointLight;
import net.logax.games.framework.gl.SpriteBatcher;
import net.logax.games.framework.gl.Texture;
import net.logax.games.framework.gl.TextureRegion;
import net.logax.games.framework.gl.Vertices3;
import net.logax.games.framework.impl.GLGame;
import net.logax.games.framework.impl.GLScreen;
import net.logax.games.framework.math.Vector2;
import net.logax.games.framework.math.Vector3;

public class MapTest extends GLGame {

	public Screen getStartScreen() {
		return new MapScreen(this);
	}

	class MapScreen extends GLScreen {
		private static final boolean LOAD_START_MODEL = true;
		private boolean canPlayerReachStart = true;
		private Texture mapTexture;
		private Texture startTexture;
		private MapCorridor mapCorridor;
		private MapCurve mapCurve;
		private MapStairs mapStairs;
		private MapStart mapStart;
		private MapYCrossing mapYCrossing;
		private MapTCrossing mapTCrossing;
		private Origin origin;
		private Texture cubeTexture;
		private Cube cube;
		private PointLight light;
		private PointLight light2;
		private PointLight light3;
		private EulerCamera camera;
		private Texture buttonTexture;
		private SpriteBatcher batcher;
		private Camera2D guiCamera;
		private TextureRegion buttonRegion;
		private Vector2 touchPos;
		private float lastX = -1;
		private float lastY = -1;

		public MapScreen(Game game) {
			super(game);

			if (LOAD_START_MODEL) {
				mapStart = new MapStart(0, 0, 1, 1);
				String modelFileName = mapStart.getModelFileName();
				Vertices3 model = ObjSerLoader.load(glGame, modelFileName);
				mapStart.setModel(model);
				startTexture = updateTextureByGameObject(startTexture, mapStart);
			}
			{
				mapCurve = new MapCurve(0, 0, 1, 1);
				String modelFileName = mapCurve.getModelFileName();
				Vertices3 model = ObjSerLoader.load(glGame, modelFileName);
				mapCurve.setModel(model);
				mapTexture = updateTextureByGameObject(mapTexture, mapCurve);
			}
			
			{
				mapCorridor = new MapCorridor(5, 0, 1, 1);
				String modelFileName = mapCorridor.getModelFileName();
				Vertices3 model = ObjSerLoader.load(glGame, modelFileName);
				mapCorridor.setModel(model);
				mapTexture = updateTextureByGameObject(mapTexture, mapCorridor);
			}
			{
				mapStairs = new MapStairs(0, 0, 6, 1);
				String modelFileName = mapStairs.getModelFileName();
				Vertices3 model = ObjSerLoader.load(glGame, modelFileName);
				mapStairs.setModel(model);
				mapTexture = updateTextureByGameObject(mapTexture, mapStairs);
			}

			{
				mapYCrossing = new MapYCrossing(0, 0, 0, 1);
				String modelFileName = mapYCrossing.getModelFileName();
				Vertices3 model = ObjSerLoader.load(glGame, modelFileName);
				mapYCrossing.setModel(model);
				mapTexture = updateTextureByGameObject(mapTexture, mapYCrossing);
			}
			{
				mapTCrossing = new MapTCrossing(0, 0, 0, 1);
				String modelFileName = mapTCrossing.getModelFileName();
				Vertices3 model = ObjSerLoader.load(glGame, modelFileName);
				mapTCrossing.setModel(model);
				mapTexture = updateTextureByGameObject(mapTexture, mapTCrossing);
			}
			{
				origin = new Origin(0, 0, 0, 1, glGraphics);

			}
			{
				cube = new Cube(0, 0, 0, 1);
				cubeTexture = updateTextureByGameObject(cubeTexture, cube);
				String modelFileName = cube.getModelFileName();
				Vertices3 model = ObjSerLoader.load(glGame, modelFileName);
				cube.setModel(model);
			}
			{
				light = new PointLight();
				light.setPosition(2, 2, -5);
				light.setDiffuse(1.0f, 1.0f, 1.0f, 1f);
			}
			{
				light2 = new PointLight();
				light2.setPosition(-3, 3, 3);
				light2.setDiffuse(0.5f, 0.5f, 0.9f, 1f);
			}
			{
				light3 = new PointLight();
				light3.setPosition(0, -3, -2);
				light3.setDiffuse(0.5f, 0.9f, 0.5f, 1f);
			}
			{
				int fieldOfView = 67;
				float aspectRatio = glGraphics.getWidth() / (float) glGraphics.getHeight();
				float near = 0.01f;
				int far = 100;
				camera = new EulerCamera(fieldOfView, aspectRatio, near, far);
				Vector3 initialPlayerPosition = new Vector3(0, 0, 3);
				camera.getPosition().set(initialPlayerPosition);
			}

			buttonTexture = new Texture(glGame, "button.png");
			batcher = new SpriteBatcher(glGraphics, 1);
			guiCamera = new Camera2D(glGraphics, 480, 320);
			buttonRegion = new TextureRegion(buttonTexture, 0, 0, 256, 256);
			touchPos = new Vector2();
		}

		private Texture updateTextureByGameObject(Texture tex, ModeledGameObject obj) {
			boolean mipMapped = true;
			String textureFileName = obj.getTextureFileName();
			if (tex != null) {
				String mapTextureFileName = tex.getFileName();
				if (mapTextureFileName != null) {
					if (!mapTextureFileName.equals(textureFileName)) {
						tex = new Texture(glGame, textureFileName, mipMapped);
						return tex;
					} else {
						return tex;
					}
				} else {
					tex = new Texture(glGame, textureFileName, mipMapped);
					return tex;
				}
			} else {
				tex = new Texture(glGame, textureFileName, mipMapped);
				return tex;
			}
		}



		@Override
		public void resume() {
			mapTexture.reload();
			buttonTexture.reload();
			cubeTexture.reload();
			if (LOAD_START_MODEL) {
				if (canPlayerReachStart) {
					startTexture.reload();
				}
			}
		}

		@Override
		public void update(float deltaTime) {
			game.getInput().getTouchEvents();
			float x = game.getInput().getTouchX(0);
			float y = game.getInput().getTouchY(0);
			guiCamera.touchToWorld(touchPos.set(x, y));

			if (game.getInput().isTouchDown(0)) {
				if (touchPos.x < 64 && touchPos.y < 64) {
					Vector3 direction = camera.getDirection();
					camera.getPosition().add(direction.mul(deltaTime * 2f));
				} else {
					if (lastX == -1) {
						lastX = x;
						lastY = y;
					} else {
						camera.rotate((x - lastX) / 5, (y - lastY) / 5);
						lastX = x;
						lastY = y;
					}
				}
			} else {
				lastX = -1;
				lastY = -1;
			}
		}

		@Override
		public void present(float deltaTime) {
			GL10 gl = glGraphics.getGL();

			gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
			gl.glClearColor(0.5f, 0.5f, 1, 1);
			gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());

			camera.setMatrices(gl);

			gl.glEnable(GL10.GL_DEPTH_TEST);
			gl.glEnable(GL10.GL_TEXTURE_2D);
			gl.glEnable(GL10.GL_LIGHTING);


			light.enable(gl, GL10.GL_LIGHT0);
//			Vector3 position2 = camera.getPosition();
//			light.setPosition(position2.x, position2.y, position2.z);
			light2.enable(gl, GL10.GL_LIGHT1);
			light3.enable(gl, GL10.GL_LIGHT2);

			ModelSolidPlotter plotter = new ModelSolidPlotter(gl);
			if (LOAD_START_MODEL) {
				if (canPlayerReachStart) {
					startTexture.bind();
					plotter.plot(mapStart);
				}
			}
			{
				{
					mapTexture.bind();

					plotter.plot(mapCorridor);
					{
						Vector3 position = new Vector3(-2, 0, -1);
						float angle = 90f;
						plotter.plotToPositionRotateCCWOnY(mapCorridor, position, angle);
					}
					plotter.plot(mapCurve);
					plotter.plot(mapStairs);
					{
						Vector3 position = new Vector3(-4, 4, -4);
						float angle = -90f;
						plotter.plotToPositionRotateCCWOnY(mapStairs, position, angle);
					}
					{
						Vector3 position = new Vector3(3, -4, 1);
						plotter.plotToPosition(mapYCrossing, position);
					}
				}
				{
					cubeTexture.bind();
					Vector3 position = new Vector3(4, 0, 0);
					plotter.plotToPosition(cube, position);
				}
			}

			gl.glDisable(GL10.GL_LIGHTING);
			gl.glDisable(GL10.GL_DEPTH_TEST);
			{
				ModelLinePlotter linePlotter = new ModelLinePlotter(gl);
				linePlotter.plot(origin);
			}
			gl.glEnable(GL10.GL_BLEND);
			gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

			guiCamera.setViewportAndMatrices();
			batcher.beginBatch(buttonTexture);
			batcher.drawSprite(32, 32, 64, 64, buttonRegion);
			batcher.endBatch();

			gl.glDisable(GL10.GL_BLEND);
			gl.glDisable(GL10.GL_TEXTURE_2D);
		}

		@Override
		public void pause() {
		}

		@Override
		public void dispose() {
		}
	}
}